package com.atguigu.srb.common.exception;

import com.atguigu.srb.common.result.R;
import com.atguigu.srb.common.result.ResponseEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.stereotype.Component;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingPathVariableException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.async.AsyncRequestTimeoutException;
import org.springframework.web.multipart.support.MissingServletRequestPartException;
import org.springframework.web.servlet.NoHandlerFoundException;

/**
 * 统一异常处理器
 * 用于捕获和处理全局范围内的异常，返回统一格式的错误响应
 * 通过@RestControllerAdvice注解捕获所有Controller层抛出的异常
 */
@Slf4j
@Component // Spring容器自动管理
@RestControllerAdvice
public class UnifiedExceptionHandler {

    /**
     * 处理未定义的通用异常
     * 作为兜底异常处理器，处理所有未被其他处理器捕获的异常
     *
     * @param e 捕获到的异常
     * @return 统一格式的错误响应
     */
    @ExceptionHandler(value = Exception.class)
    public R handleException(Exception e) {
        log.error("系统未知异常：", e);
        return R.error();
    }

    /**
     * 处理SQL语法错误异常
     * 当执行SQL语句时出现语法错误时触发
     *
     * @param e SQL语法错误异常
     * @return 统一格式的错误响应，包含特定错误信息
     */
    @ExceptionHandler(BadSqlGrammarException.class)
    public R handleBadSqlGrammarException(BadSqlGrammarException e) {
        log.error("SQL语法错误：", e);
        return R.setResult(ResponseEnum.BAD_SQL_GRAMMAR_ERROR);
    }

    /**
     * 处理业务自定义异常
     * 用于处理业务逻辑中主动抛出的异常
     *
     * @param e 业务异常
     * @return 统一格式的错误响应，包含自定义错误码和错误信息
     */
    @ExceptionHandler(BusinessException.class)
    public R handleBusinessException(BusinessException e) {
        log.error("业务异常：", e);
        return R.error().message(e.getMessage()).code(e.getCode());
    }

    /**
     * 处理Controller层相关异常
     * 捕获并处理HTTP请求处理过程中的各种异常
     *
     * @param e Controller层异常
     * @return 统一格式的错误响应，包含Servlet请求异常信息
     */
    @ExceptionHandler({NoHandlerFoundException.class,              // 未找到处理请求的处理器
            HttpRequestMethodNotSupportedException.class, // 请求方法不支持
            HttpMediaTypeNotSupportedException.class,   // 媒体类型不支持
            MissingPathVariableException.class,         // 缺少路径变量
            MissingServletRequestParameterException.class, // 缺少请求参数
            TypeMismatchException.class,                // 类型不匹配
            HttpMessageNotReadableException.class,      // HTTP消息不可读
            HttpMessageNotWritableException.class,      // HTTP消息不可写
            MethodArgumentNotValidException.class,      // 方法参数无效
            HttpMediaTypeNotAcceptableException.class,  // 媒体类型不可接受
            ServletRequestBindingException.class,       // Servlet请求绑定异常
            ConversionNotSupportedException.class,      // 转换不支持
            MissingServletRequestPartException.class,   // 缺少请求部分
            AsyncRequestTimeoutException.class          // 异步请求超时
    })
    public R handleServletException(Exception e) {
        log.error("Servlet请求异常：", e);
        // SERVLET_ERROR(-102, "servlet请求异常"),
        return R.error().message(ResponseEnum.SERVLET_ERROR.getMessage()).code(ResponseEnum.SERVLET_ERROR.getCode());
    }
}